#include <string.h>
#include <fcntl.h>
#include "aos/cli.h"
#include "aos/kernel.h"
#include "aos/yloop.h"
#include "aos/kv.h"
#include "if_v.h"
#include "wrapper.h"
//#include "facelib.h"
#include "vfs.h"
#include "cli_api.h"
#include "camera_config.h"
#include "net_param.h"
#include "userFaceSample.h"
#include "jpegConvert.h"
#include "drv_delay.h"
//#include "analysislog.h"

/******************************************************
 *                      Macros
 ******************************************************/
/******************************************************
 *                    Constants
 ******************************************************/


extern int ifv_debug_level;
extern int g_ifVsaveRgbEnable;
extern int g_ifVsaveIrEnable;
extern int g_ifVUnmaskEnable;
extern int g_ifVispMiInTEnable;
extern tsmMatchParam g_matchparam;
extern uint32_t aie_ir_detect_enable;
extern int g_omx_debug;
int g_mi_debug;
/******************************************************
 *                   Enumerations
 ******************************************************/

/******************************************************
 *                 Type Definitions
 ******************************************************/

/******************************************************
 *                    Structures
 ******************************************************/
void if_v_command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv);
void handle_ff_cmd(char *pwbuf, int blen, int argc, char **argv);
void _cli_if_v_help_command(int argc, char **argv);
void if_vSaveRgbToFile(uint32_t ulRgbFileIndex);
void if_vSaveIrToFile(void);

extern int writeFlashRegisterType(uint8_t *register_type);
extern int jpeg_to_ir(char *jpeg_buffer, int jpeg_buffer_len, char *ir_buffer);
extern void ir_to_jpeg(unsigned char *imageData, unsigned char **compressedBuffer, int imageWidth,
                       int imageHeight, int channels, unsigned long *outSize);
struct cli_command_st if_v_message_cmd[] = {
    {"ifv", "ifv [ reg | recog ]", if_v_command},
    {"ff", "ff [ list | del <ff id> | clear ]", handle_ff_cmd},
};

/******************************************************
 *               Function Declarations
 ******************************************************/
uint32_t g_ulIfvDebugEnable = false;
uint32_t g_ulMatchScoreEnable = false;

uint32_t g_ulIfvusbupdate = false;
uint32_t g_usbPicSaveEnable = false;

uint8_t g_imageAcquisitionFlag = 0;

/******************************************************
 *               Variables Definitions
 ******************************************************/

/******************************************************
 *               Function Definitions
 ******************************************************/
unsigned char *ifv_cli_buff = NULL;
void ifv_test_recog(char *out_buffer)
{
    if (!ifv_cli_buff)
    {
        return;
    }

    memcpy(out_buffer, ifv_cli_buff, 360 * 640);

    free(ifv_cli_buff);
    ifv_cli_buff = NULL;
}
#ifdef AOS_COMP_FATFS
int ifv_face_reg_raw(char *vis_pic)
{
    int ret;
    identifyID id;
    if_v_register register_info;

    memset(&id, 0, sizeof(id));
    memset(&register_info, 0, sizeof(register_info));

    register_info.info = &id;
    register_info.pic_w = 360;
    register_info.pic_h = 640;
    register_info.pic_size = 360 * 640 * 4;
    register_info.buff = (unsigned char *)vis_pic;
    register_info.pic_mode = IFV_REGISTER_MODE_PIC_RAW;

    ret = if_vRegister(&register_info);
    //printf("FR reg face id if_vRegister ret=[%d]\n", ret);

    return 0;
}

int ifv_face_reg_jpg(char *vis_pic, int pic_size)
{
    int ret;
    identifyID id;
    if_v_register register_info;

    memset(&id, 0, sizeof(id));
    memset(&register_info, 0, sizeof(register_info));

    register_info.info = &id;
    register_info.pic_w = 360;
    register_info.pic_h = 640;
    register_info.pic_size = pic_size;
    register_info.buff = (unsigned char *)vis_pic;
    register_info.pic_mode = IFV_REGISTER_MODE_PIC_JPG;

    ret = if_vRegister(&register_info);
    //printf("FR reg face id if_vRegister ret=[%d]\n", ret);

    return 0;
}
#endif
uint8_t register_by_ir = 1;
void ifv_load_aie_thres(float *thres_2d, float *thres_3d, float *thres_recog, float *thres_recog_mask)
{
    int32_t ret = 0;
    float thres_3d_local; // thres_2d_local, thres_recog_local, thres_recog_mask_local;
    int len = sizeof(float);

    if (thres_2d)
    {
        if_vThres2dGet(thres_2d);
    }

    ret = aos_kv_get(IFV_CLI_THRES_3D, &thres_3d_local, &len);
    if ((ret == 0) && (thres_3d))
    {
        *thres_3d = thres_3d_local;
    }

    if (thres_recog)
    {
        if_vThresRecoGet(thres_recog);
    }

    if (thres_recog_mask)
    {
        if_vThresMaskRecoGet(thres_recog_mask);
    }
}

uint32_t load_file(unsigned char **buff, const char *path)
{
    int fd = -1;
    int ret;
    //char temp_buf[512] = {0};
    //uint32_t len = 0;
    struct aos_stat file_st;
    uint32_t file_len = 0;
    uint32_t pfont;
    pfont = (uint32_t)(*buff);

    fd = aos_open((const char *)path, O_RDONLY);
    if (fd < 0)
    {
        printf("aos_open err.\n");
        goto exit;
    }

    ret = aos_stat(path, &file_st);
    if (!ret)
    {
        file_len = file_st.st_size;
    }

    printf("file len %d\n", file_len);

    *buff = (unsigned char *)aos_malloc(file_len);
    if (!*buff)
    {
        printf("aos_malloc err.\n");
        goto exit;
    }

    ret = aos_read(fd, *buff, file_len);

    printf("ret %d\n", ret);

exit:
    if (fd >= 0)
    {
        aos_close(fd);
    }

    return file_len;
}

#if 1
void userCmdGetRGBSnapShot()
{
    //	int len = 360 * 640 * 4;
    int len = 800 * 600 * 4;
    unsigned long outSize = 0;

    unsigned char *pBuffer = aos_malloc(len);
    unsigned char *pJpegBuffer;

    if (NULL == pBuffer)
    {
        printf("Failed to alloc memory\r\n");
        return;
    }

    if_vGetRGBSnapShot(pBuffer, len);
    rgba_to_jpeg(pBuffer,
                 &pJpegBuffer,
                 600,
                 800,
                 4,
                 &outSize);

    printf("get snapshot pic.\n");
    aos_free(pBuffer);
    aos_free(pJpegBuffer);
}
#endif

extern uint8_t g_runmode_cover;
extern uint8_t g_aieresult_print;
uint8_t g_sensor_type = 0;
extern uint32_t g_uvc_preview_mode_enable;
extern g_variable_control_t g_variable_cfg;
static void _cli_if_v_command(int argc, char **argv)
{
    int ret = 0;
    float thres = 0;

    const char *rtype = argc > 0 ? argv[0] : "";

    if (strcmp(rtype, "testmode") == 0)
    {
        int32_t ret = 0;
        uint32_t testModeIndex = 0;

        if (argc < 2)
        {
            return;
        }
        testModeIndex = atoi(argv[1]);
        aos_kv_set(IFV_RUNNING_TEST_MODE, &testModeIndex, sizeof(testModeIndex), 1);

        printf("_cli_if_v_command reg face id if_vRegister ret=[%d]\n", ret);
    }
    else if (strcmp(rtype, "usb_update") == 0)
    {
        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        if (strcmp(argv[1], "enable") == 0)
        {
            g_ulIfvusbupdate = true;
            ret = aos_kv_set(IFV_USB_FIRMWARE_ENABLE, &g_ulIfvusbupdate, sizeof(g_ulIfvusbupdate), 1);
            if (ret != 0)
            {
                printf("Failed to enable usb update\r\n");
            }
        }
        else if (strcmp(argv[1], "disable") == 0)
        {
            g_ulIfvusbupdate = false;
            ret = aos_kv_set(IFV_USB_FIRMWARE_ENABLE, &g_ulIfvusbupdate, sizeof(g_ulIfvusbupdate), 1);
            if (ret != 0)
            {
                printf("Failed to disable usb update\r\n");
            }
        }
    }
    else if (strcmp(rtype, "usb_pic_save") == 0)
    {
        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        if (strcmp(argv[1], "enable") == 0)
        {
            g_usbPicSaveEnable = true;
            ret = aos_kv_set(IFV_USB_PIC_SAVE_ENABLE, &g_usbPicSaveEnable, sizeof(g_usbPicSaveEnable), 1);
            if (ret != 0)
            {
                printf("Failed to enable usb pic save\r\n");
            }
        }
        else if (strcmp(argv[1], "disable") == 0)
        {
            g_usbPicSaveEnable = false;
            ret = aos_kv_set(IFV_USB_PIC_SAVE_ENABLE, &g_usbPicSaveEnable, sizeof(g_usbPicSaveEnable), 1);
            if (ret != 0)
            {
                printf("Failed to disable usb pic save\r\n");
            }
        }
    }
    else if (strcmp(rtype, "preview_uvc") == 0)
    {
        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        if (strcmp(argv[1], "enable") == 0)
        {
            g_uvc_preview_mode_enable = true;
            ret = aos_kv_set(IFV_UVC_PREVIEW_MODE, &g_uvc_preview_mode_enable, sizeof(g_uvc_preview_mode_enable), 1);
            if (ret != 0)
            {
                printf("enable UVC preview mode\r\n");
            }
        }
        else if (strcmp(argv[1], "disable") == 0)
        {
            g_uvc_preview_mode_enable = false;
            ret = aos_kv_set(IFV_UVC_PREVIEW_MODE, &g_uvc_preview_mode_enable, sizeof(g_uvc_preview_mode_enable), 1);
            if (ret != 0)
            {
                printf("disable UVC preview mode\r\n");
            }
        }
    }
    else if (strcmp(rtype, "reg") == 0)
    {
        ifv_msg_pkg_t msg;
        msg.cmd = APP2IFV_REGISTER_CMD;
        ifv_post_msg(msg);

        printf("_cli_if_v_command reg face id if_vRegister ret=[%d]\n", ret);
    }
    else if (strcmp(rtype, "calib") == 0)
    {
        extern g_variable_control_t g_variable_cfg;
        if (1 == g_ifv_flow_cfg.depth_doubleIr_enable)
        {
            g_variable_cfg.g_calib_estimate_dif_LR2 = 50.0f;
            g_variable_cfg.g_calibration_loop_count = 1;
            ifv_msg_pkg_t msg;
            msg.cmd = APP2IFV_CALIBRATION_CMD;
            ifv_post_msg(msg);

            printf("_cli_if_v_command reg face id if_vCalibration ret=[%d]\n", ret);
        }
        else
            printf("double ir depth is disable!");
    }
    else if (strcmp(rtype, "reg_ir") == 0)
    {
        register_by_ir = 1;
        writeFlashRegisterType(&register_by_ir);
        printf("register by ir\n");
    }
    else if (strcmp(rtype, "reg_vis") == 0)
    {
        register_by_ir = 0;
        writeFlashRegisterType(&register_by_ir);
        printf("register by vis\n");
    }
    else if (strcmp(rtype, "reg_mult") == 0)
    {
        if (argc < 3)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        printf("register by multi \n");
        user_multi_angle_reg_sample_run(0, NULL, atoi(argv[1]), atoi(argv[2]), 0xFFFF);
    }
    else if (strcmp(rtype, "reg_mult_id") == 0)
    {
        if (argc < 4)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        printf("resign id register by multi  \n");
        user_multi_angle_reg_sample_run(0, NULL, atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
    }
    else if (strcmp(rtype, "reg_mult_cancel") == 0)
    {
        user_multi_angle_reg_stop();
    }
    else if (strcmp(rtype, "reg_mult_save") == 0)
    {
        printf("save begin\n");
        user_face_manage_ff_add(0);
        printf("save end\n");
    }
    else if (strcmp(rtype, "reg_mult_del") == 0)
    {
        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        printf("del begin\n");
        user_face_manage_ff_delete(atoi(argv[1]));
        printf("del end\n");
    }
    else if (strcmp(rtype, "reg_mult_del_range") == 0)
    {
        if (argc < 3)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        printf("del begin\n");
        if_vDelRange(atoi(argv[1]), atoi(argv[2]));
        printf("del end\n");
    }
    else if (strcmp(rtype, "set_matchthres") == 0)
    {
        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }
        else
        {
            float match_thres = atof(argv[1]);
            ret = aos_kv_set(IFV_CLI_THRES_RECOG, &match_thres, sizeof(float), 1);
            if (ret != 0)
            {
                printf("Failed to set face match thres\r\n");
            }
            ifv_load_aie_thres(NULL,
                               NULL,
                               &g_matchparam.threshold,
                               NULL);
            printf("set face match thres to: %f\n", g_matchparam.threshold);
            // ret = aos_kv_set(IFV_SET_FACEMATCHTHRES, &match_thres, sizeof(float), 1);
            // if (ret != 0)
            // {
            //     printf("Failed to set face match thres\r\n");
            // }
            uint8_t match_thres_flag = true;
            ret = aos_kv_set(IFV_SET_FACEMATCHTHRES_FLAG, &match_thres_flag, sizeof(uint8_t), 1);
            if (ret != 0)
            {
                printf("Failed to set face match thres\r\n");
            }
        }
    }
    else if (strcmp(rtype, "get_matchthres") == 0)
    {
        float match_thres_value = 0.0;
        ifv_load_aie_thres(NULL,
                           NULL,
                           &match_thres_value,
                           NULL);
        printf("face match thres is : %f\n", match_thres_value);
    }
    else if (strcmp(rtype, "set_runmodecover") == 0)
    {
        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }
        uint8_t cover_mode;
        if (strcmp(argv[1], "enable") == 0)
        {
            cover_mode = true;
            g_runmode_cover = true;
            ret = aos_kv_set(IFV_RUNMODE_COVER, &cover_mode, sizeof(cover_mode), 1);
            if (ret != 0)
            {
                printf("Failed to enable set_runmodecover\r\n");
            }
        }
        else if (strcmp(argv[1], "disable") == 0)
        {
            cover_mode = false;
            g_runmode_cover = false;
            ret = aos_kv_set(IFV_RUNMODE_COVER, &cover_mode, sizeof(cover_mode), 1);
            if (ret != 0)
            {
                printf("Failed to disable set_runmodecover\r\n");
            }
        }
    }
    else if (strcmp(rtype, "set_aieprint") == 0)
    {
        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }
        uint8_t aieresault_print;
        if (strcmp(argv[1], "enable") == 0)
        {
            aieresault_print = true;
            g_aieresult_print = true;
            ret = aos_kv_set(IFV_AIERESULT_PRINT_TIMES, &aieresault_print, sizeof(aieresault_print), 1);
            if (ret != 0)
            {
                printf("Failed to enable set_aieprint\r\n");
            }
        }
        else if (strcmp(argv[1], "disable") == 0)
        {
            aieresault_print = false;
            g_aieresult_print = false;
            ret = aos_kv_set(IFV_AIERESULT_PRINT_TIMES, &aieresault_print, sizeof(aieresault_print), 1);
            if (ret != 0)
            {
                printf("Failed to disable set_aieprint\r\n");
            }
        }
    }
    else if (strcmp(rtype, "recog") == 0)
    {
        ifv_msg_pkg_t msg;

        if (strcmp(argv[1], "ir_detect") == 0)
        {
            aie_ir_detect_enable = 1;
        }
        else
        {
            aie_ir_detect_enable = 0;
        }
        msg.cmd = APP2IFV_RECOGNIZE_CMD;
        ifv_post_msg(msg);
    }
    else if (strcmp(rtype, "sensor_l") == 0)
    {
        g_sensor_type = 0;
    }
    else if (strcmp(rtype, "sensor_r") == 0)
    {
        g_sensor_type = 1;
    }
    else if (strcmp(rtype, "mscore") == 0)
    {
        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        if (strcmp(argv[1], "enable") == 0)
        {
            g_ulMatchScoreEnable = true;
        }
        else if (strcmp(argv[1], "disable") == 0)
        {
            g_ulMatchScoreEnable = false;
        }
    }
#ifdef AOS_COMP_FATFS
    else if (strcmp(rtype, "reg_pic") == 0)
    {
        uint32_t temp_debug = 0;

        if (1 == argc)
        {
            load_file(&ifv_cli_buff, FS_ROOT_PATH "/reg_pic.raw");
        }
        else if (2 == argc)
        {
            load_file(&ifv_cli_buff, argv[1]);
        }
        else
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        temp_debug = g_ulIfvDebugEnable;
        g_ulIfvDebugEnable = false;
        if (ifv_face_reg_raw((char *)ifv_cli_buff) < 0)
        {
            printf("Regist failed\n");
        }
        aos_msleep(1000);
        g_ulIfvDebugEnable = temp_debug;

        free(ifv_cli_buff);
        ifv_cli_buff = NULL;
    }
    else if (strcmp(rtype, "recog_pic") == 0)
    {
        ifv_msg_pkg_t msg;

        if (1 == argc)
        {
            load_file(&ifv_cli_buff, FS_ROOT_PATH "/recog_pic.raw");
        }
        else if (2 == argc)
        {
            load_file(&ifv_cli_buff, argv[1]);
        }
        else
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        msg.cmd = APP2IFV_RECOGNIZE_CMD;
        ifv_post_msg(msg);
    }
    else if (strcmp(rtype, "reg_dir") == 0)
    {
        char path[128] = {0};
        aos_dir_t *dp;
        aos_dirent_t *out_dirent;
        uint32_t temp_debug = 0;

        dp = (aos_dir_t *)aos_opendir(IFV_RGB_DIR_ROOT);

        if (!dp)
        {
            printf("aos_opendir [%s] fail\r\n", IFV_RGB_DIR_ROOT);
            return;
        }

        while (1)
        {
            uint32_t file_len = 0;
            char *jpeg_buffer = NULL;

            //ifv_cli_buff = aos_malloc(IFV_IR_PIC_WIDTH * IFV_IR_PIC_HIGHT * 4);
            //if (NULL == ifv_cli_buff)
            //{
            //    printf("aos_malloc failed\r\n");
            //    return;
            //}

            out_dirent = (aos_dirent_t *)aos_readdir(dp);
            if (!out_dirent)
            {
                break;
            }
            printf("Register with %s\r\n", out_dirent->d_name);
            if (strncmp(out_dirent->d_name, "RGB_", strlen("RGB_")))
            {
                continue;
            }

            sprintf(path, "%s/%s", IFV_RGB_DIR_ROOT, out_dirent->d_name);
            file_len = load_file((unsigned char **)&jpeg_buffer, path);
            //jpeg_to_rgba(jpeg_buffer, file_len, ifv_cli_buff);

            temp_debug = g_ulIfvDebugEnable;
            g_ulIfvDebugEnable = false;
            if (ifv_face_reg_jpg(jpeg_buffer, file_len) < 0)
            {
                printf("Regist failed\n");
            }
            aos_msleep(3000);
            g_ulIfvDebugEnable = temp_debug;
            //free(ifv_cli_buff);
            //ifv_cli_buff = NULL;
            if (jpeg_buffer)
                free(jpeg_buffer);
        }

        aos_closedir(dp);
    }
    else if (strcmp(rtype, "recog_dir") == 0)
    {
        char path[128] = {0};
        aos_dir_t *dp;
        aos_dirent_t *out_dirent;
        ifv_msg_pkg_t msg;

        dp = (aos_dir_t *)aos_opendir(IFV_IR_DIR_ROOT);

        if (!dp)
        {
            printf("aos_opendir [%s] fail\r\n", IFV_IR_DIR_ROOT);
            return;
        }

        while (1)
        {
            uint32_t file_len = 0;
            char *jpeg_buffer = NULL;

            out_dirent = (aos_dirent_t *)aos_readdir(dp);
            if (!out_dirent)
            {
                break;
            }

            if (strncmp(out_dirent->d_name, "IR_", strlen("IR_")))
            {
                continue;
            }

            ifv_cli_buff = aos_malloc(IFV_IR_PIC_WIDTH * IFV_IR_PIC_HIGHT);
            if (NULL == ifv_cli_buff)
            {
                printf("aos_malloc failed\r\n");
                return;
            }
            extern uint32_t if_vGet_RunningState();
            while ((if_vGet_RunningState() != APP2IFV_CMD_STATE_NONE) && (if_vGet_RunningState() != APP2IFV_RECOGNIZE_CMD_STATE_COMPLETE))
                aos_msleep(1000);
            printf("Recognize with %s\r\n", out_dirent->d_name);
            sprintf(path, "%s/%s", IFV_IR_DIR_ROOT, out_dirent->d_name);
            file_len = load_file((unsigned char **)&jpeg_buffer, path);
            jpeg_to_ir(jpeg_buffer, file_len, (char *)ifv_cli_buff);

            msg.cmd = APP2IFV_RECOGNIZE_CMD;
            ifv_post_msg(msg);
            aos_msleep(2000);

            free(ifv_cli_buff);
            ifv_cli_buff = NULL;
            free(jpeg_buffer);
        }

        aos_closedir(dp);
    }
    else if (strcmp(rtype, "recog_dir_raw") == 0)
    {
        char path[128] = {0};
        aos_dir_t *dp;
        aos_dirent_t *out_dirent;
        ifv_msg_pkg_t msg;
        // const char * pExt;

        dp = (aos_dir_t *)aos_opendir(IFV_IR_DIR_ROOT);

        if (!dp)
        {
            printf("aos_opendir [%s] fail\r\n", IFV_IR_DIR_ROOT);
            return;
        }

        while (1)
        {
            uint32_t file_len = 0;
            out_dirent = (aos_dirent_t *)aos_readdir(dp);
            if (!out_dirent)
            {
                break;
            }

            // if (strncmp(out_dirent->d_name, "IR_", strlen("IR_")))
            // {
            //     continue;
            // }
            // pExt = strrchr(out_dirent->d_name, '.');
            // if ( pExt != NULL )
            // {
            //     if (strcmp(pExt, ".raw") == 0){
            //         //printf("raw 文件！\n");
            //     }else{
            //         printf("非raw文件:%s！\n", out_dirent->d_name);
            //         continue;
            //     }
            // }else{
            //     printf("无后缀名文件:%s\n", out_dirent->d_name);
            //     continue;
            // }

            printf("Recognize with %s\r\n", out_dirent->d_name);
            sprintf(path, "%s/%s", IFV_IR_DIR_ROOT, out_dirent->d_name);

            file_len = load_file(&ifv_cli_buff, path);
            // printf("file_len=%d, sizeof(ifv_cli_buff)=%d\r\n", file_len, sizeof(ifv_cli_buff));

            msg.cmd = APP2IFV_RECOGNIZE_CMD;
            ifv_post_msg(msg);
            aos_msleep(3000);

            aos_free(ifv_cli_buff);
            ifv_cli_buff = NULL;
        }

        aos_closedir(dp);
    }
#endif
    else if (strcmp(rtype, "debug") == 0)
    {
        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        if (strcmp(argv[1], "enable") == 0)
        {
            g_ulIfvDebugEnable = true;
            ret = aos_kv_set(IFV_CLI_DEBUG, &g_ulIfvDebugEnable, sizeof(g_ulIfvDebugEnable), 1);
            if (ret != 0)
            {
                printf("Failed to enable ifv debug\r\n");
            }
        }
        else if (strcmp(argv[1], "disable") == 0)
        {
            g_ulIfvDebugEnable = false;
            ret = aos_kv_set(IFV_CLI_DEBUG, &g_ulIfvDebugEnable, sizeof(g_ulIfvDebugEnable), 1);
            if (ret != 0)
            {
                printf("Failed to disable ifv debug\r\n");
            }
        }
    }
    else if (strcmp(rtype, "loglevel") == 0)
    {
        if (argc < 2)
        {
            printf("loglevel 0/1/2/3/4/5\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        ifv_debug_level = atoi(argv[1]);
    }
    else if (strcmp(rtype, "thres") == 0)
    {
        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        if (strcmp(argv[1], "2d") == 0)
        {
            thres = atof(argv[2]);
            if_vThres2dSet(thres);
        }
        else if (strcmp(argv[1], "3d") == 0)
        {
            thres = atof(argv[2]);
            ret = aos_kv_set(IFV_CLI_THRES_3D, &thres, sizeof(thres), 1);
            if (ret != 0)
            {
                printf("Failed to set 3d thres\r\n");
            }
        }
        else if (strcmp(argv[1], "recog") == 0)
        {
            thres = atof(argv[2]);
            if_vThresRecoSet(thres);
        }
        else if (strcmp(argv[1], "recog_mask") == 0)
        {
            thres = atof(argv[2]);
            ret = aos_kv_set(IFV_CLI_THRES_RECOG_MASK, &thres, sizeof(thres), 1);
            if (ret != 0)
            {
                printf("Failed to set recog mask thres\r\n");
            }
        }
        else if (strcmp(argv[1], "show") == 0)
        {
            float thres_2d = 0, thres_recog = 0, thres_recog_mask = 0;
            ifv_load_aie_thres(&thres_2d,
                               NULL,
                               &thres_recog,
                               &thres_recog_mask);
            printf("    Threshold 2D:           %f\r\n", thres_2d);
            printf("    Threshold Recog:        %f\r\n", thres_recog);
            printf("    Threshold RecogM:       %f\r\n", thres_recog_mask);
        }
    }
    else if (strcmp(rtype, "image_mode") == 0)
    {
        uint32_t mode;

        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        if (strcmp(argv[1], "rgb") == 0)
        {
            mode = 1;
        }
        else if (strcmp(argv[1], "ir") == 0)
        {
            mode = 0;
        }

        ret = aos_kv_set(IFV_CLI_IMAGE_MODE, &mode, sizeof(mode), 1);
        if (ret != 0)
        {
            printf("Failed to set ifv image mode\r\n");
        }
        else
        {
            if_vSetVisReco(mode);
        }
    }
    else if (strcmp(rtype, "snapshot") == 0)
    {
        // uint32_t mode;

        if (argc < 2)
        {
            printf("Invalid command\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }
#ifdef AOS_COMP_FATFS
        if (strcmp(argv[1], "rgb") == 0)
        {
            if_vSaveRgbToFile(0xffffffff);
        }
        else if (strcmp(argv[1], "ir") == 0)
        {
            if_vSaveIrToFile();
        }
#else
        printf("Invalid command\n");
        _cli_if_v_help_command(0, NULL);
        return;
#endif
    }
    else if (strcmp(rtype, "savergb") == 0)
    {
        if (argc < 2)
        {
            printf("savergb 0/1\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        g_ifVsaveRgbEnable = atoi(argv[1]);
    }
    else if (strcmp(rtype, "saveir") == 0)
    {
        if (argc < 2)
        {
            printf("saveir 0/1\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        g_ifVsaveIrEnable = atoi(argv[1]);
    }
    else if (strcmp(rtype, "unmask") == 0)
    {
        if (argc < 2)
        {
            printf("unmask 0/1\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        g_ifVUnmaskEnable = atoi(argv[1]);
    }
    else if (strcmp(rtype, "ispmi") == 0)
    {
        if (argc < 2)
        {
            printf("ispmi idx 0/1\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        g_ifVispMiInTEnable = atoi(argv[2]);
    }
    else if (strcmp(rtype, "omx_debug") == 0)
    {
        if (argc < 2)
        {
            printf("omx_debug 0/1\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        g_omx_debug = atoi(argv[1]);
    }
    else if (strcmp(rtype, "mi_debug") == 0)
    {
        if (argc < 2)
        {
            printf("mi_debug 0x0, 0x1, 0x2, 0x4\n");
            _cli_if_v_help_command(0, NULL);
            return;
        }

        g_mi_debug = atoi(argv[1]);
    }
    else if (strcmp(rtype, "ff_boot_clear") == 0)
    {
        extern int ff_set_boot_nonfirst();
        ff_set_boot_nonfirst();
    }
#if 0
    else if (strcmp(rtype, "recog_usb") == 0){
            int rawType=0;
            int temp = g_usbPicSaveEnable;

            g_usbPicSaveEnable = 0;

            if (argc < 2)
            {
                rawType=1;
            }else
                rawType=atoi(argv[1]);
            g_omx_debug=1;
            if(g_app_flow_cfg.source_ir_left)
                usbRawToAlgo(rawType);
            else
                BaseLine_usbRawToAlgo(rawType,g_app_flow_cfg.source_spk);

            g_usbPicSaveEnable = temp;           
    }
    else if (strcmp(rtype, "recog_folder_usb") == 0){
            int rawType=0;
            int folderNum=0;
            int temp = g_usbPicSaveEnable;

            g_usbPicSaveEnable = 0;

            printf("resign folder recog\n");

            if (argc < 3)
            {
               printf("para error! \n");
               return;
            }
            
            rawType=atoi(argv[1]);
            folderNum = atoi(argv[2]);
            g_omx_debug=1;
            if(g_app_flow_cfg.source_ir_left)
                usbRawFolderToAlgo(rawType, folderNum);

            g_usbPicSaveEnable = temp;           
    }
    else if (strcmp(rtype, "calib_usb") == 0){
            int rawType=0;
            int temp = g_usbPicSaveEnable;

            g_usbPicSaveEnable = 0;
            g_variable_cfg.g_calib_not_save_flag = 1;

            if (argc < 2)
            {
                rawType=1;
            }else
                rawType=atoi(argv[1]);
            g_omx_debug=1;
            if(g_app_flow_cfg.depth_doubleIr_enable)
                usbCalibRawToAlgo(rawType);

            g_usbPicSaveEnable = temp;     
            g_variable_cfg.g_calib_not_save_flag = 0;
            g_variable_cfg.g_calibration_loop_count = 1;
    }
    else if (strcmp(rtype, "calib_n_usb") == 0){
            int rawType=0;
            int rawNumber = 0;
            int temp = g_usbPicSaveEnable;

            printf("resign image number recalib\n");
            if (argc < 3)
            {
               printf("para error! \n");
               return;
            }

            g_usbPicSaveEnable = 0;
            g_variable_cfg.g_calib_not_save_flag = 1;
            rawType=atoi(argv[1]);
            rawNumber = atoi(argv[2]);
            g_omx_debug=1;
            if(g_app_flow_cfg.depth_doubleIr_enable)
                usbCalibRawNumToAlgo(rawType, rawNumber);

            g_usbPicSaveEnable = temp;     
            g_variable_cfg.g_calib_not_save_flag = 0;      
    }
    else if (strcmp(rtype, "calib_n_estimate_m_usb") == 0){
            int rawType=0;
            int rawNumber = 0;
            int estimateNumber = 0;
            int temp = g_usbPicSaveEnable;

            printf("resign image number recalib and estimate!\n");
            if (argc < 4)
            {
               printf("para error! \n");
               return;
            }

            g_usbPicSaveEnable = 0;
            g_variable_cfg.g_calib_not_save_flag = 1;
            g_variable_cfg.g_read_pic_by_usb_flag = 1;
            rawType=atoi(argv[1]);
            rawNumber = atoi(argv[2]);
            estimateNumber = atoi(argv[3]);
            g_omx_debug=1;
            if(g_app_flow_cfg.depth_doubleIr_enable)
                usbCalibEstimateRawNumToAlgo(rawType, rawNumber, estimateNumber);

            g_usbPicSaveEnable = temp;     
            g_variable_cfg.g_calib_not_save_flag = 0;      
            g_variable_cfg.g_read_pic_by_usb_flag = 0;
    }
    else if (strcmp(rtype, "calib_folder_estimate_m_usb") == 0){
            int rawType=0;
            int folderNumber = 0;
            int estimateNumber = 0;
            int temp = g_usbPicSaveEnable;

            printf("resign image folder recalib and estimate!\n");
            if (argc < 4)
            {
               printf("para error! \n");
               return;
            }

            g_usbPicSaveEnable = 0;
            g_variable_cfg.g_calib_not_save_flag = 1;
            g_variable_cfg.g_read_pic_by_usb_flag = 1;
            rawType=atoi(argv[1]);
            folderNumber = atoi(argv[2]);
            estimateNumber = atoi(argv[3]);
            g_omx_debug=1;
            if(g_app_flow_cfg.depth_doubleIr_enable)
                usbCalibFolderEstRawNumToAlgo(rawType, folderNumber, estimateNumber);

            g_usbPicSaveEnable = temp;     
            g_variable_cfg.g_calib_not_save_flag = 0;      
            g_variable_cfg.g_read_pic_by_usb_flag = 0;
    }
#endif
    else if (strcmp(rtype, "image_acquisition") == 0)
    {
        if (0 == g_imageAcquisitionFlag)
        {
            g_imageAcquisitionFlag |= 0x1;

            printf("[image_acquisition] start\n");

            ifv_msg_pkg_t msg;
            msg.cmd = APP2IFV_RECOGNIZE_CMD;
            ifv_post_msg(msg);
        }
        else
        {
            g_imageAcquisitionFlag |= 0x3;
            printf("[image_acquisition] will stop\n");
        }
    }
    else if (strcmp(rtype, "jpeg") == 0)
    {

        userCmdGetRGBSnapShot();
    }

    return;
}

void handle_ff_cmd(char *pwbuf, int blen, int argc, char **argv)
{
    int res = 0;

    const char *rtype = argc > 1 ? argv[1] : "";

    if (strcmp(rtype, "del") == 0)
    {
        if (argc != 3)
        {
            return;
        }

        res = tsm_ff_delete(atoi(argv[2]));
        if (res < 0)
        {
            cli_printf("Failed to delete face feature %d(%d)\r\n", atoi(argv[2]), res);
        }
        else
        {
            cli_printf("Success to delete face feature with id %d\r\n", atoi(argv[2]));
        }
    }
    else if (strcmp(rtype, "list") == 0)
    {
        tsm_ff_dump_id();
    }
    else if (strcmp(rtype, "list_user") == 0)
    {
        user_ff_dump_id();
    }
    else if (strcmp(rtype, "clear") == 0)
    {
        res = tsm_ff_clear();
        if (res < 0)
        {
            cli_printf("Failed to clear face feature %d\r\n", res);
        }
        else
        {
            cli_printf("Success to clear all face feature\r\n");
        }
    }
    else if (strcmp(rtype, "clear_user") == 0)
    {
        res = user_face_manage_ff_clear();
        if (res < 0)
        {
            cli_printf("Failed to clear face feature %d\r\n", res);
        }
        else
        {
            cli_printf("Success to clear all face feature\r\n");
        }
    }
    else if (strcmp(rtype, "clear_ff_flag") == 0)
    {
        int ff_first_boot_flag = 0;

        res = aos_kv_set("ff_check_first_boot", &ff_first_boot_flag, 1, 1);
        if (res != 0)
        {
            cli_printf("Failed to clear FF_CHECK_FIRST_BOOT %d\r\n", res);
        }
        else
        {
            cli_printf("Success to clear FF_CHECK_FIRST_BOOT %d\r\n", res);
        }
    }

    return;
}

void _cli_if_v_help_command(int argc, char **argv)
{
    printf("Usage: ifv\n");
    printf("  ifv reg,        Register face by sensor\n");
    printf("  ifv reg_pic,    Register face by a raw picture file\n");
    printf("  ifv recog_pic,  Recognize face by jpg picture files \n");
    printf("  ifv recog_pic_raw,  Recognize face by raw picture files\n");
    printf("  ifv thres < 2d <thres> | 3d <thres> | recog <thres> | show >,  Alg threshold configuration\n");
    printf("  ifv saveir 0/1\n");
    printf("  ifv savergb 0/1\n");
    printf("  ifv unmask 0/1, 1: close mask detect, 0: normal\n");
    printf("  ifv omx_debug 0/1, 1: enable omx debug, 0: disable\n");
    printf("  ifv recog_usb 1/2, 1: recog raw pic with 360x640, 2: 600x800\n");
    printf("\n");
}

void if_v_command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
{
    // int i = 0;
    // ifv_msg_pkg_t msg;

    //printf("========= %s argc %d======== \n",__func__,argc);

    //msg.cmd = 0;
    //ifv_post_msg(msg);

    //aos_post_event(EV_IFV, IFV_CMD_REGISTER, 0);

    if (argc < 2)
    {
        printf("Invalid command\n");
        _cli_if_v_help_command(0, NULL);
        return;
    }

    if (strcmp(argv[1], "-h") == 0)
    {
        _cli_if_v_help_command(argc - 2, &argv[2]);
    }
    else
    {
        _cli_if_v_command(argc - 1, &argv[1]);
    }
}

#ifdef AOS_COMP_FATFS
extern void if_v_service_event(input_event_t *event, void *priv_data);
//extern int ov2732_get_exposure_para(regval_list *expo_arg);
void if_vSaveIrToFile()
{
    int fd = -1;
    uint8_t ucFilePath[128] = {0};
    int32_t ret = 0;
    uint32_t ulIrFileIndex = 0;
    int len = sizeof(ulIrFileIndex);
    unsigned long outSize = 0;
    unsigned char *pJpegBuffer = NULL;

    ret = aos_kv_get(IFV_IR_FILE_INDEX, &ulIrFileIndex, &len);
    if ((ret == -ENOENT) || (ulIrFileIndex >= IFV_FILE_IR_MAX_INDEX))
    {
        ulIrFileIndex = 1;
    }

    // regval_list expo_arg[] = {
    //     {0x3501,0x0},   //expo H
    //     {0x3502,0x0},   //expo L
    // 	{0x3508,0x0},	//gain
    //     {0x3509,0x0},   //gain
    // };
#if 0
    ov2732_get_exposure_para(expo_arg);
    
    sprintf(ucFilePath, "%s/IR_%d_0x%x_0x%x_0x%x_0x%x.jpg", 
            IFV_IR_DIR_ROOT, ulIrFileIndex,
            expo_arg[0].data, expo_arg[1].data, expo_arg[2].data, expo_arg[3].data);
#else
    sprintf((char *)ucFilePath, "%s/IR_%d.jpg",
            IFV_IR_DIR_ROOT, ulIrFileIndex);
#endif
    fd = aos_open((const char *)ucFilePath, O_RDWR | O_CREAT | O_TRUNC);
    if (fd < 0)
    {
        printf("aos_open err.\n");
        goto exit;
    }

    //lv_write_myFontsimsun28_text("Saving...");
    //lv_write_myFontsimsun28_text(ucFilePath);

    ir_to_jpeg(iva_facereco_ir_get_buffer(0, 0),
               &pJpegBuffer,
               IFV_IR_PIC_WIDTH,
               IFV_IR_PIC_HIGHT,
               1,
               &outSize);

    if (aos_write(fd, (char *)pJpegBuffer, outSize) != outSize)
    {
        printf("aos_write err.\n");
        goto exit;
    }

    mdelay(1000);

    ulIrFileIndex++;
    ret = aos_kv_set(IFV_IR_FILE_INDEX, &ulIrFileIndex, sizeof(ulIrFileIndex), 1);
    if (ret != 0)
    {
        printf("Failed to save ir file index\r\n");
        goto exit;
    }

    printf("save picture %s.\n", ucFilePath);
exit:
    if (fd >= 0)
    {
        aos_close(fd);
    }

    if (pJpegBuffer)
    {
        aos_free(pJpegBuffer);
    }
}
static uint32_t g_ulRgbFileIndex = 1;
extern int ov2732_rgb_get_exposure_para(regval_list *expo_arg);
void if_vSaveRgbToFile(uint32_t ulRgbFileIndex)
{
    int fd = -1;
    uint8_t ucFilePath[128] = {0};
    // int32_t ret = 0;
    unsigned long outSize = 0;
    unsigned char *pJpegBuffer = NULL;

    if (0xffffffff == ulRgbFileIndex)
    {
        ulRgbFileIndex = g_ulRgbFileIndex++;
    }
#if 0
    regval_list expo_arg[] = { 
        {0x3501,0x0},   //expo H		
        {0x3502,0x0},   //expo L
		{0x3508,0x0},	//gain
        {0x3509,0x0},   //gain
    };

    ov2732_rgb_get_exposure_para(expo_arg);

    for (uint32_t i = 0; i < 4;  i++)
    {
        printf("0x%x: 0x%x\r\n", expo_arg[i].addr, expo_arg[i].data);
    }
    
    sprintf(ucFilePath, "%s/RGB_%d_0x%x_0x%x_0x%x_0x%x.jpg", 
            IFV_RGB_DIR_ROOT, ulRgbFileIndex,
            expo_arg[0].data, expo_arg[1].data, expo_arg[2].data, expo_arg[3].data);
#else
    sprintf((char *)ucFilePath, "%s/RGB_%d.jpg",
            IFV_RGB_DIR_ROOT, ulRgbFileIndex);
#endif

    fd = aos_open((char *)ucFilePath, O_RDWR | O_CREAT | O_TRUNC);
    if (fd < 0)
    {
        printf("aos_open err.\n");
        goto exit;
    }

    //lv_write_myFontsimsun28_text("Saving...");
    //lv_write_myFontsimsun28_text(ucFilePath);
    rgba_to_jpeg(IFV_RGB_BASE_ADDR,
                 &pJpegBuffer,
                 IFV_RGB_PIC_WIDTH,
                 IFV_RGB_PIC_HIGHT,
                 4,
                 &outSize);

    if (aos_write(fd, (char *)pJpegBuffer, outSize) != outSize)
    {
        printf("aos_write err.\n");
        goto exit;
    }

    printf("save picture %s.\n", ucFilePath);
exit:
    if (fd >= 0)
    {
        aos_close(fd);
    }

    if (pJpegBuffer)
    {
        aos_free(pJpegBuffer);
    }
}
#endif
void if_vDelRgbFile(uint32_t ulRgbFileIndex)
{
    uint8_t ucFilePath[128] = {0};

    sprintf((char *)ucFilePath, "%s/RGB_%d.jpg", IFV_RGB_DIR_ROOT, ulRgbFileIndex);
    aos_unlink((const char *)ucFilePath);
}

void if_vDebugInit()
{
    int32_t ret = 0;
    int len = sizeof(g_ulIfvDebugEnable);
    aos_dir_t *dp;

    aos_kv_get(IFV_CLI_DEBUG, &g_ulIfvDebugEnable, &len);

    dp = (aos_dir_t *)aos_opendir(IFV_IR_DIR_ROOT);
    if (!dp)
    {
        ret = aos_mkdir(IFV_IR_DIR_ROOT);
    }
    else
    {
        ret = aos_closedir(dp);
    }

    dp = (aos_dir_t *)aos_opendir(IFV_RGB_DIR_ROOT);
    if (!dp)
    {
        ret = aos_mkdir(IFV_RGB_DIR_ROOT);
    }
    else
    {
        ret = aos_closedir(dp);
    }
}

int if_v_cli_register(void)
{
    int ret;

    // aos_task_new("ifv_config_main", ifv_config_entry, NULL, 8192);
    ret = cli_register_commands(if_v_message_cmd, 2);

    return ret;
}
